#############################
#
# 电子发票（铁路电子客票）解析
#
#############################
from .invoice import Invoice
import re
from pymupdf import Page

RAILWAY_INVOICE_BASE_PATTRNS = {
    "invoice_number": r"发票号码\s*[:：]?\s*(\d{20})",
    "date": r"开票日期\s*[:：]?\s*(\d{4}年\d{2}月\d{2}日)",
    "amount": r"[\w\W]*?([¥￥]?\s*\d+[.\.]\d{2})",
}


def get_railway_invoice_base_info_from_page(page) -> dict:
    """
    从铁路电子客票页面中获取基本的发票信息
    :param page: 页面对象
    :return: 发票信息字典
    """
    result = {}
    # 获取页面文本内容
    # 使用sort=True参数可以确保文本按照页面的顺序获取
    # 这样可以避免文本被打乱顺序
    page_text = page.get_text("text", sort=True)
    text_list = page_text.split()
    for key, str_pattern in RAILWAY_INVOICE_BASE_PATTRNS.items():
        for text in text_list:
            if re.match(str_pattern, text):
                result[key] = re.search(str_pattern, text).group(1)
                break
    return result


RAILWAY_INVOICE_DETAIL_PATTRNS = {
    "passenger": r"\d{10}\*{4}\d{3}[X\d]",
    "departure_date": r"^\d{4}年\d{2}月\d{2}日",
    "departure_time": r"^\d{2}:\d{2}开",
    "train_number": r"[GKZDT]\d{1,4}",
    "seat": r"\w+[座卧]",
}


def get_text_index(text_list, pattern: str) -> int:
    """
    在文本列表中查找匹配正则表达式模式的文本，并返回其索引

    Parameters
    ==========

    text_list: list 文本列表
    pattern: str 正则表达式模式

    Return
    ======
    int 匹配文本的索引，如果未找到则返回-1

    """
    for index, text in enumerate(text_list):
        if re.match(pattern, text):
            return index
    return -1


def get_railway_invoice_detail_info_from_page(page: Page) -> dict:
    """
    从铁路电子客票页面中获取具体的发票信息
    :param page: 页面对象
    :return: 发票信息字典
    """
    page_text = page.get_text("text", sort=True)
    text_list = page_text.split()
    # 初始化结果字典
    result = {}

    for key, str_pattern in RAILWAY_INVOICE_DETAIL_PATTRNS.items():
        index = get_text_index(text_list, str_pattern)
        if index != -1:
            result[key] = re.search(str_pattern, text_list[index]).group(0)
        else:
            result[key] = None
    # 利用文本之间的位置关系获取更多信息
    train_number_index = get_text_index(
        text_list, RAILWAY_INVOICE_DETAIL_PATTRNS["train_number"]
    )
    if train_number_index != -1:
        result["begin_station"] = text_list[train_number_index - 1]
        result["end_station"] = text_list[train_number_index + 1]
    passenger_index = get_text_index(
        text_list, RAILWAY_INVOICE_DETAIL_PATTRNS["passenger"]
    )
    if passenger_index != -1:
        result["passenger_name"] = text_list[passenger_index + 1]
    return result


def get_railway_invoice_info_from_page(page: Page) -> dict:
    """
    从铁路电子客票页面中获取发票的基本信息和详细信息
    Parameter
    =========
    page: 页面对象
    Return
    ======
    dict: 发票信息字典
    """
    base_info = get_railway_invoice_base_info_from_page(page)
    detail_info = get_railway_invoice_detail_info_from_page(page)
    return {
        **base_info,
        **detail_info,
        "details": f"{detail_info.get('begin_station', '')} {detail_info.get('train_number', '')} {detail_info.get('end_station', '')} {detail_info.get('departure_date', '')} {detail_info.get('departure_time', '')} {detail_info.get('seat', '')}",
    }


class RailwayInvoice(Invoice):
    def __init__(self, page: Page):
        self._invoice_base_info = get_railway_invoice_base_info_from_page(page)
        if not self._invoice_base_info:
            raise ValueError("无法从页面中获取铁路电子客票的基本信息")
        self._invoice_detail_info = get_railway_invoice_detail_info_from_page(page)
        if not self._invoice_detail_info:
            raise ValueError("无法从页面中获取铁路电子客票的详细信息")

    @property
    def invoice_number(self) -> int:
        return int(self._invoice_base_info.get("invoice_number", 0))

    @property
    def date(self) -> str:
        return self._invoice_base_info.get("date", "")

    @property
    def amount(self) -> float:
        return float(
            re.search(r"[\d.]+", self._invoice_base_info.get("amount", "0")).group()
        )

    @property
    def passenger_name(self) -> str:
        return self._invoice_detail_info.get("passenger_name", "")

    @property
    def train_number(self) -> str:
        return self._invoice_detail_info.get("train_number", "")

    @property
    def seat(self) -> str:
        return self._invoice_detail_info.get("seat", "")

    @property
    def departure_times(self) -> str:
        return (
            self._invoice_detail_info.get("departure_date", "")
            + " "
            + self._invoice_detail_info.get("departure_time", "")
        )

    @property
    def begin_station(self) -> str:
        return self._invoice_detail_info.get("begin_station", "")

    @property
    def end_station(self) -> str:
        return self._invoice_detail_info.get("end_station", "")

    @property
    def details(self) -> str:
        return (
            f"{self.begin_station} {self.train_number} {self.end_station} "
            f"出发时间: {self.departure_times} "
            f"座次: {self.seat}"
        )
